#include "BlockQueue.hpp"
#include "Task.hpp"

using namespace std;

string symbol = "+-*/%";

template <class C, class S>
class BlockQueues
{
public:
    BlockQueue<C> *c_bq; // 计算队列
    BlockQueue<S> *s_bq; // 保存队列

    BlockQueues()
    {
        c_bq = new BlockQueue<C>();
        s_bq = new BlockQueue<S>();
    }
    ~BlockQueues()
    {
        delete c_bq;
        delete s_bq;
    }
};

void *Producer(void *arg)
{
    BlockQueue<CalTask> *c_bq = static_cast<BlockQueues<CalTask, SaveTask> *>(arg)->c_bq;
    while (1)
    {
        int data_x = rand() % 10;
        int sym_index = rand() % symbol.size();
        int data_y = rand() % 10;
        CalTask t(data_x, data_y, symbol[sym_index]);
        c_bq->Push(t);
        cout << "生产数据：" << t.Print() << endl;
        sleep(1);
    }
    return nullptr;
}
void *Consumer(void *arg)
{
    BlockQueue<CalTask> *c_bq = static_cast<BlockQueues<CalTask, SaveTask> *>(arg)->c_bq;
    BlockQueue<SaveTask> *s_bq = static_cast<BlockQueues<CalTask, SaveTask> *>(arg)->s_bq;
    while (1)
    {
        // 消费计算队列中生产的数据
        CalTask t;
        c_bq->Pop(&t);
        cout << "消费数据：" << t.Calculate() << endl;

        // 保存消费者的结果到保存队列中
        SaveTask st(t.Calculate());
        s_bq->Push(st);
        cout << "推送数据完成" << endl;
        // sleep(1);
    }
    return nullptr;
}

void *Saver(void *arg)
{
    BlockQueue<SaveTask> *s_bq = static_cast<BlockQueues<CalTask, SaveTask> *>(arg)->s_bq;
    while (1)
    {
        SaveTask st;
        s_bq->Pop(&st);
        st.Save();
        cout << "保存数据完成" << endl;
    }
}
int main()
{
    srand(time(0) ^ getpid());
    BlockQueues<CalTask, SaveTask> *bqs = new BlockQueues<CalTask, SaveTask>();
    // bqs->c_bq=new BlockQueue<CalTask>();
    // bqs->s_bq=new BlockQueue<SaveTask>();

    pthread_t pro, con, sav;
    pthread_create(&pro, nullptr, Producer, bqs);
    pthread_create(&con, nullptr, Consumer, bqs);
    pthread_create(&sav, nullptr, Saver, bqs);

    pthread_join(pro, nullptr);
    pthread_join(con, nullptr);
    pthread_join(sav, nullptr);
    delete bqs;
}